const axios = require('axios');
const axiosConfig = require('../config/axiosConfig');
const { calculateLimitUpDays } = require('../method');
const { getWeekPriceCache, getLowPriceCache, getHighPriceCache } = require('./cachedController');
const baseUrl = 'https://push2his.eastmoney.com/api/qt/stock/kline/get';
const listUrl = 'https://push2.eastmoney.com/api/qt/clist/get';
const infoUrl = 'https://push2.eastmoney.com/api/qt/stock/get';
const infoList = 'https://push2.eastmoney.com/api/qt/ulist.np/get';

function calculateWeekPrice(code) {
    const weekPrices = getWeekPriceCache();
    let priceInfo = weekPrices[code] || [];
    let threeDayChange = 0;
    let fiveDayChange = 0;
    let limitUpDays = 0;
    if (priceInfo.length > 0) {
        // 计算3日和5日涨幅
        threeDayChange =
            priceInfo.length >= 3
                ? (
                    ((priceInfo[0] * 1 - priceInfo[2] * 1) / (priceInfo[2] * 1)) *
                    100
                ).toFixed(2)
                : 0;
        fiveDayChange =
            priceInfo.length >= 5
                ? (
                    ((priceInfo[0] * 1 - priceInfo[4] * 1) / (priceInfo[4] * 1)) *
                    100
                ).toFixed(2)
                : 0;

        // 计算连板天数
        limitUpDays = calculateLimitUpDays(priceInfo, code);
    }
    return { threeDayChange, fiveDayChange, limitUpDays }
}

/**
 * @description 获取所有股票列表
 */
const getStockList = async (totalPages) => {
    try {
        // 分页获取所有数据
        const pageSize = 100;
        let allStocks = [];

        // 创建所有页面的请求数组
        const pageRequests = Array.from({ length: totalPages }, (_, i) => {
            const params = {
                pn: i + 1, // 页码
                pz: pageSize, // 每页数量
                po: 0, // 不排序
                np: 1,
                ut: '7eea3edcaed734bea9cbfc24409ed989',
                fltt: 2,
                invt: 2,
                fid: 'f62',
                fs: 'm:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23',
                fields: 'f1,f2,f3,f5,f6,f7,f8,f9,f10,f12,f14,f21,f22,f23,f34,f35,f37,f45,f49,f57,f62,f66,f72,f78,f84,f100,f102,f103,f129,f133'
            };
            // f108 连板天数
            return axios.get(listUrl, {
                ...axiosConfig,
                params
            });
        });

        // 并发请求所有页面数据
        const responses = await Promise.all(pageRequests);

        // 处理每页数据
        for (const response of responses) {
            if (!response.data.data || !response.data.data.diff) continue;

            const currentPageStocks = response.data.data.diff.map((item) => {
                // const { threeDayChange, fiveDayChange, limitUpDays } =
                //     calculateWeekPrice(item.f12);
                const lowPriceInfo = getLowPriceCache();
                const highPriceInfo = getHighPriceCache();
                return {
                    code: item.f12,
                    name: item.f14,
                    price: parseFloat(item.f2) || 0,
                    changePercent: parseFloat(item.f3) || 0,
                    changePrice: parseFloat(item.f4) || 0,
                    totalHands: item.f5,
                    transactionVolume: item.f6,
                    currentHand: item.f30,
                    threeDayChange: 0,
                    fiveDayChange: 0,
                    turnoverRate: item.f8,
                    volumeRatio: item.f10,
                    mainMoneyNet: item.f62,
                    f66: item.f66,
                    f72: item.f72,
                    f78: item.f78,
                    f84: item.f84,
                    pe: item.f9,
                    pb: item.f23,
                    IOHandicap: Number(item.f34) - Number(item.f35) || 0,
                    yieldRate: item.f133 === '-' ? 0 : parseFloat(item.f133),
                    sector: item.f100,
                    region: item.f102,
                    concept: item.f103,
                    lowPrice: lowPriceInfo[item.f12] || '',
                    highPrice: highPriceInfo[item.f12] || '',
                    roe: parseFloat(item.f37).toFixed(2), //净资产收益率
                    growthRate: parseFloat(item.f22).toFixed(2), //涨速
                    grossMargin: parseFloat(item.f49).toFixed(2), //毛利率
                    netMargin: parseFloat(item.f129).toFixed(2), //净利率
                    ratio: parseFloat(item.f57).toFixed(2), //资产负责率
                    marketValue: item.f21,
                    limitUpDays: 0,
                };
            });

            allStocks = allStocks.concat(currentPageStocks);
            // 为了避免请求过于频繁，增加延时
            await new Promise((resolve) => setTimeout(resolve, 200));
        }
        // 过滤掉无效数据
        const validStocks = allStocks.filter(
            (stock) => stock.price > 0 && stock.name && stock.code
        );
        return validStocks;
    } catch (error) {
        console.error('获取股票列表失败');
        return [];
    }
};
/**
 * @description 获取股票历史数据
 */
const getStockHistory = async (code) => {
    try {
        const params = {
            secid: `${code.startsWith('6') ? 1 : 0}.${code}`,
            ut: 'fa5fd1943c7b386f172d6893dbfba10b',
            fields1: 'f1,f2,f3,f4,f5,f6',
            fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
            klt: 101,
            fqt: 1,
            end: 20500101,
            lmt: 5
        };

        const response = await axios.get(baseUrl, { params });
        if (response.data.data && response.data.data.klines) {
            const klines = response.data.data.klines.reverse();
            return klines.map((line) => {
                const [date, open, close, high, low, volume] = line.split(',');
                return {
                    date,
                    price: parseFloat(close)
                };
            });
        }

        return [];
    } catch (error) {
        console.error('获取历史数据失败');
        return [];
    }
};

// 获取股票近5天的数据
const getWeekStockPrice = async (codes) => {
    try {
        const weekStockPrice = await Promise.all(
            codes.map(async (code) => {
                try {
                    const params = {
                        secid: `${code.startsWith('6') ? 1 : 0}.${code}`,
                        ut: 'bd1d9ddb04089700cf9c27f6f7426281',
                        fields1: 'f1,f2,f3,f4,f5,f6',
                        fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
                        klt: 101,
                        fqt: 1,
                        end: 20500101,
                        lmt: 5
                    };

                    const res = await axios.get(baseUrl, {
                        ...axiosConfig,
                        params
                    });

                    if (res.data.data && res.data.data.klines) {
                        const klines = res.data.data.klines.reverse();
                        const history = klines.map((line) => {
                            // 日期，今开，今闭，今日最高，今日最低，震幅
                            const [date, open, close, high, low, volume] = line.split(',');
                            return {
                                price: close
                            };
                        });
                        return {
                            [code]: history.map((h) => h.price)
                        };
                    }
                    return [];
                } catch (error) {
                    return [];
                }
            })
        );
        return weekStockPrice;
    } catch (error) {
        console.error('获取股票近5天数据失败');
        return [];
    }
};

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

// 获取所有股票数据
const getAllStock = async () => {
    const lowPriceInfo = getLowPriceCache();
    let stockCodes = Object.keys(lowPriceInfo);
    try {
        let res1 = await getStocksByCode(stockCodes.slice(0, 2600));

        await delay(60000 + Math.random() * 300000);
        let res2 = await getStocksByCode(stockCodes.slice(2600));
        return [...res1, ...res2];
    } catch (error) {
        console.error('获取所有股票数据失败');
        return [];
    }
};

// 根据股票编码获取股票最新数据
const getStocksByCode = async (codes) => {
    try {
        // 并发请求每个股票的数据
        const promises = codes.map((code) => {
            const params = {
                ut: '7eea3edcaed734bea9cbfc24409ed989',
                invt: 2,
                fltt: 2,
                fields:
                    'f43,f44,f45,f46,f47,f48,f49,f50,f51,f52,f55,f57,f58,f60,f62,f71,f78,f80,f84,f85,f86,f92,f104,f105,f107,f110,f111,f116,f117,f127,f128,f129,f135,f136,f137,f138,f139,f140,f141,f142,f143,f144,f145,f146,f147,f148,f149,f152,f161,f162,f163,f164,f167,f168,f169,f170,f171,f173,f177,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f193,f194,f195,f196,f197,f198,f199,f250,f251,f252,f253,f254,f255,f256,f257,f258,f259,f260,f261,f262,f263,f264,f265,f266,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f277,f278,f279,f280,f281,f282,f284,f285,f286,f287,f288,f289,f290,f292,f293,f294,f295',
                secid: `${code.startsWith('6') ? '1' : '0'}.${code}`
            };
            return axios.get(infoUrl, { ...axiosConfig, params });
        });

        // 等待所有请求完成
        const responses = await Promise.all(promises);

        // 处理响应数据
        const result = responses
            .filter((response) => response.data && response.data.data)
            .map((response) => {
                const data = response.data.data;
                const { threeDayChange, fiveDayChange, limitUpDays } =
                    calculateWeekPrice(data.f57);
                const lowPriceInfo = getLowPriceCache();
                const highPriceInfo = getHighPriceCache();
                return {
                    code: data.f57, // 股票代码
                    name: data.f58, // 股票名称
                    price: data.f43, // 当前价格
                    changePercent: data.f170, // 涨跌幅
                    volumeRatio: data.f50, // 量比
                    turnoverRate: data.f168, // 换手率
                    pe: data.f164, // 市盈率（动）
                    pb: data.f167, // 市净率
                    limitUpPrice: data.f51, // 涨停价
                    mainMoneyNet: data.f137, // 主力资金净流入（元）
                    changePrice: parseFloat(data.f43 - data.f46) || 0,
                    totalHands: data.f47, //总手
                    transactionVolume: data.f48, //交易额
                    currentHand: '-',
                    threeDayChange: parseFloat(threeDayChange), // 3日涨幅
                    fiveDayChange: parseFloat(fiveDayChange), // 5日涨幅
                    sector: data.f127, // 板块
                    region: data.f128, // 地区
                    concept: data.f129, // 概念
                    lowPrice: lowPriceInfo[data.f57] || '', // 最低价
                    highPrice: highPriceInfo[data.f57] || '', // 最高价
                    roe: parseFloat(data.f173).toFixed(2), // 净资产收益率
                    ratio: parseFloat(data.f188).toFixed(2), // 资产负债率
                    growthRate: '-', // 涨速
                    grossMargin: parseFloat(data.f186).toFixed(2), // 毛利率
                    netMargin: parseFloat(data.f187).toFixed(2), // 净利率
                    marketValue: data.f117, // 流值
                    limitUpDays
                };
            });
        return result;
    } catch (error) {
        console.error('获取股票最新数据失败');
        return [];
    }
};

// 获取股票板块、地区、概念、净资产收益率、资产负债率信息
const getStockInfoByCode = async (codes) => {
    try {
        // 并发请求每个股票的数据
        const promises = codes.map((code) => {
            const params = {
                ut: 'fa5fd1943c7b386f172d6893dbfba10b',
                invt: 2,
                fltt: 2,
                fields: 'f57,f127,f128,f129,f173,f188',
                secid: `${code.startsWith('6') ? '1' : '0'}.${code}`
            };
            return axios.get(infoUrl, { ...axiosConfig, params });
        });

        // 等待所有请求完成
        const responses = await Promise.all(promises);

        // 处理响应数据
        const result = responses
            .filter((response) => response.data && response.data.data)
            .map((response) => {
                const data = response.data.data;
                return {
                    code: data.f57, // 股票代码
                    sector: data.f127, // 板块信息
                    region: data.f128, // 地区信息
                    concept: data.f129, // 概念信息
                    roe: parseFloat(data.f173).toFixed(2), // 净资产收益率
                    assetRatio: parseFloat(data.f188).toFixed(2) // 资产负债率
                };
            });
        return result;
    } catch (error) {
        console.error('获取股票板块、地区、概念、净资产收益率、资产负债率信息失败');
        return [];
    }
};

// 获取股票近100天的数据
const getHistoryStockPrice = async (codes, type = 'high') => {
    try {
        const historyStockPrice = await Promise.all(
            codes.map(async (code) => {
                try {
                    const params = {
                        secid: `${code.startsWith('6') ? 1 : 0}.${code}`,
                        ut: '7eea3edcaed734bea9cbfc24409ed989',
                        fields1: 'f1,f2,f3,f4,f5,f6',
                        fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
                        klt: 101,
                        fqt: 1,
                        end: 20500101,
                        lmt: 100
                    };

                    const res = await axios.get(baseUrl, {
                        ...axiosConfig,
                        params
                    });

                    if (res.data.data && res.data.data.klines) {
                        const klines = res.data.data.klines.reverse();
                        const history = klines.map((line) => {
                            // 日期，今开，今闭，今日最高，今日最低，震幅
                            const [date, open, close, high, low, volume] = line.split(',');
                            return {
                                price: type === 'high' ? high : low
                            };
                        });
                        const historyPrices = history.map((h) => h.price);
                        return {
                            [code]: historyPrices
                        };
                    }
                    return [];
                } catch (error) {
                    return [];
                }
            })
        );
        return historyStockPrice;
    } catch (error) {
        console.error('获取股票近100天数据失败');
        return [];
    }
};

module.exports = {
    getStockList,
    getAllStock,
    getStockInfoByCode,
    getWeekStockPrice,
    getHistoryStockPrice
};
